﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hardcodet.Wpf.GenericTreeView;
using Csla.Core;
using Csla;
using Ricciolo.Controls;
using System.Windows.Controls;
using System.Windows.Data;
using System.ComponentModel;
using System.Collections;
using System.Collections.ObjectModel;
using OpenExpressApp.MetaModel;
using System.Windows.Input;
using System.Windows;
using System.Windows.Media;
using OpenExpressApp.Module.WPF.Editors.TreeColumn;
using OpenExpressApp.Module.WPF;

namespace OpenExpressApp.WPF.Controls
{
    public class ObjectTreeView : TreeViewBase<ITreeNode>
    {
        public Dictionary<object, TreeListViewItem> ObjectTreeViewItems = new Dictionary<object, TreeListViewItem>();
        
        public ObjectTreeView()
        {
            base.Tree = new TreeListView();
            this.SelectedItemChanged +=new RoutedTreeItemEventHandler<ITreeNode>(ObjectTreeView_SelectedItemChanged);
            this.SetValue(KeyboardNavigation.TabNavigationProperty, KeyboardNavigationMode.Contained);
            RootPid = null;  //默认Pid=null加载树
            LazyTreeNodeRelation = true; //都按懒加载关系处理
        }

        public bool IsReadOnly { get; set; }
        private bool lazyTreeNodeRelation;
        private bool LazyTreeNodeRelation 
        {
            get { return lazyTreeNodeRelation; }
            set
            {
                lazyTreeNodeRelation = value;
                PreserveLayoutOnRefresh = !lazyTreeNodeRelation;  //如果懒加载关系，则不保留扩展关系
                ObserveChildItems = !value;
            }
        }
        
        //for  LazyTreeNodeRelation
        protected override bool HasChildItems(ITreeNode parent)
        {               
            //Id可能是整形或Guid
            string curId = parent.Id.ToString();
            foreach (ITreeNode item in itemsSource)
            {
                object itemId = item.Pid;
                if ((null != itemId) && (itemId.ToString() == curId))
                    return true;
            }
            return false;
        }

        public void Expand(ITreeNode node)
        {
            TreeListViewItem curItem = ObjectTreeViewItems[node.Id];
            curItem.IsExpanded = true;
            foreach (TreeViewItem item in curItem.Items)
            {
                ITreeNode n = item.Header as ITreeNode;
                if (HasChildItems(n)) Expand(n);
            }
       }

        protected override void OnNodeExpanded(TreeViewItem treeNode)
        {
            if (LazyTreeNodeRelation && treeNode.HasItems && ((treeNode.Header as ITreeNode).ChildrenNodes.Count == 0))
            {
                //Id可能是整形或Guid
                string curId = (treeNode.Header as ITreeNode).Id.ToString();
                foreach (ITreeNode item in itemsSource)
                {
                    object itemId = item.Pid;
                    if ((null != itemId) && (itemId.ToString() == curId))
                        (item as ITreeNode).ParentNode = treeNode.Header as ITreeNode;
                }
            }
            base.OnNodeExpanded(treeNode);
        }

        public TreeListView Tree
        {
            get
            {
                return (TreeListView)(base.Tree);
            }
        }

        public object RootPid 
        { 
            set 
            {
                bind(value);
            } 
        }
        private void bind(object rootPid)
        {
            Tree.Items.Clear();
            ObjectTreeViewItems.Clear();  //必须放在base之前，因为CreateTreeViewItem在base内部执行
            Items = null;
            roots.Clear();
            selectedItems.Clear();
            if (null != itemsSource)
            {
                foreach (var item in itemsSource)
                {
                    //todo: Guid和其他类型作为主键到时分为两个组件，混在一起代码比较混乱
                    if (rootPid is Guid)
                    {
                        if ((null != (item as ITreeNode).Pid) && ((Guid)rootPid == (Guid)(item as ITreeNode).Pid)) //ParentNode)
                        {
                            roots.Add(item as ITreeNode);
                        }
                    }
                    else
                    {
                        if (rootPid == (item as ITreeNode).Pid) //ParentNode)
                        {
                            roots.Add(item as ITreeNode);
                        }
                    }
                }
            }

            Items = roots;
        }

        private ObservableCollection<ITreeNode> roots = new ObservableCollection<ITreeNode>(); //必须为ObservableCollection,这样会根节点会自动更新
        private IList itemsSource;
        public IList ItemsSource
        {
            get
            {
                return itemsSource;
            }
            set
            {
                itemsSource = value;
                bind(null);
            }
        }


        protected override TreeView CreateTreeView()
        {
            return new TreeListView();
        }

        protected override TreeViewItem CreateTreeViewItem(ITreeNode item)
        {
            TreeListViewItem treeListViewItem = null;
            ObjectTreeViewItems.Remove(item.Id);
            treeListViewItem = new TreeListViewItem();
            ObjectTreeViewItems.Add(item.Id, treeListViewItem);
            //赋值DataContext，否则TreeColumn生成的控件绑定有问题
            treeListViewItem.DataContext = item;  
            return treeListViewItem;
        }

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);

        }

        public override string GetItemKey(ITreeNode item)
        {
            return item.Id.ToString();
        }

        public override ICollection<ITreeNode> GetChildItems(ITreeNode parent)
        {
            return parent.ChildrenNodes;
        }

        public override ITreeNode GetParentItem(ITreeNode item)
        {
            return item.ParentNode;
        }

        public void RemoveNode(ITreeNode item)
        {
            //如果还未扩展建立此节点，则退出
            if (!ObjectTreeViewItems.ContainsKey(item.Id))  return;

            TreeListViewItem curItem = ObjectTreeViewItems[item.Id];
            if (curItem.Parent is TreeViewItem)
                (curItem.Parent as TreeViewItem).Items.Remove(curItem);
            else
                Tree.Items.Remove(curItem);
        }

        #region  支持多选        
        
        // a set of all selected items
        private IList selectedItems = new List<ITreeNode>();
        public IList SelectedItems
        {
            get { return selectedItems; }
        }

        // true only while left ctrl key is pressed
        bool CtrlPressed
        {
            get
            {
                return System.Windows.Input.Keyboard.IsKeyDown(Key.LeftCtrl);
            }
        }

        void ObjectTreeView_SelectedItemChanged(object sender, RoutedTreeItemEventArgs<ITreeNode> e)
        {
            TreeViewItem treeViewItem = Tree.SelectedItem as TreeViewItem;

            if (treeViewItem == null)
                return;

            // prevent the WPF tree item selection 
            treeViewItem.IsSelected = false;

            treeViewItem.Focus();

            if (!CtrlPressed)
            {
                List<ITreeNode> selectedTreeViewItemList = new List<ITreeNode>();
                foreach (ITreeNode item in selectedItems)
                {
                    selectedTreeViewItemList.Add(item);
                }

                foreach (ITreeNode item in selectedTreeViewItemList)
                {
                    Deselect(ObjectTreeViewItems[item.Id]);
                }
            }

            ChangeSelectedState(treeViewItem);
        }

        private void Deselect(TreeViewItem treeViewItem)
        {
            treeViewItem.Background = Brushes.White;// change background and foreground colors
            treeViewItem.Foreground = Brushes.Black;
            selectedItems.Remove(treeViewItem.DataContext); // remove the item from the selected items set
        }

        private void ChangeSelectedState(TreeViewItem treeViewItem)
        {
            if (!selectedItems.Contains(treeViewItem.DataContext))
            { // select
                treeViewItem.Background = Brushes.CornflowerBlue; // change background and foreground colors
                treeViewItem.Foreground = Brushes.White;
                selectedItems.Add(treeViewItem.DataContext); // add the item to selected items
            }
            else
            { // deselect
                Deselect(treeViewItem);
            }
        }

        internal void SelectAll()
        {
            ExpandAll();
            selectedItems.Clear();
            foreach (ITreeNode item in itemsSource)
            {
                ChangeSelectedState(ObjectTreeViewItems[item.Id]);
            }
        }

        # endregion

        #region  支持键盘
        
        protected override void OnKeyDown(KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Tab:
                    OnTabKeyDown(e);
                    break;

                case Key.Enter:
                    OnEnterKeyDown(e);
                    break;

                case Key.Left:
                case Key.Right:
                case Key.Up:
                case Key.Down:
                    OnArrowKeyDown(e);
                    break;

                case Key.Home:
                case Key.End:
                    OnHomeOrEndKeyDown(e);
                    break;

                case Key.PageUp:
                case Key.PageDown:
                    OnPageUpOrDownKeyDown(e);
                    break;
            }

            if (!e.Handled)
            {
                base.OnKeyDown(e);
            }
        }

        private void OnPageUpOrDownKeyDown(KeyEventArgs e)
        {
           // throw new NotImplementedException();
        }

        private void OnHomeOrEndKeyDown(KeyEventArgs e)
        {
          //  throw new NotImplementedException();
        }

        private void OnArrowKeyDown(KeyEventArgs e)
        {
           // throw new NotImplementedException();
        }

        private void OnEnterKeyDown(KeyEventArgs e)
        {
           // throw new NotImplementedException();
        }

        /// <summary>
        ///     Called when the tab key is pressed to perform focus navigation.
        /// </summary>
        private void OnTabKeyDown(KeyEventArgs e)
        {
            bool previous = ((e.KeyboardDevice.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift);
            // Start navigation from the current focus to allow moveing focus on other focusable elements inside the cell
            //UIElement startElement = Keyboard.FocusedElement as UIElement;
            UIElement startElement = e.OriginalSource as UIElement;
            if (startElement != null)
            {
                e.Handled = true;
                FocusNavigationDirection direction = previous ? FocusNavigationDirection.Previous : FocusNavigationDirection.Next;
                TraversalRequest request = new TraversalRequest(direction);
                request.Wrapped = true; // Navigate only within treeGrid
                startElement.MoveFocus(request);
            }
        }
        
        # endregion
    }

    public static class ObjectTreeViewExtensionMethods
    {


        public static void UpdateContentTemplate(this TreeListViewItem lvi, bool isEditing)
        {
            // get the row presenter which holds all the column visuals per item
            GridViewRowPresenter rowPresenter = lvi.GetVisualChild<GridViewRowPresenter>();

            //新增树节点时还未显示界面时，需要手动调用一下ApplyTemplate
            if (null == rowPresenter)
            {
                lvi.ApplyTemplate();
                rowPresenter = lvi.GetVisualChild<GridViewRowPresenter>();
                rowPresenter.Columns = lvi.GetLogicalParent<TreeListView>().Columns;
                rowPresenter.ApplyTemplate();
            }

            // go through each column and update the content template
            int columnIndex = 0;
            foreach (GridViewColumn column in rowPresenter.Columns)
            {
                // get the content presenter of the particular column
                ContentPresenter cp = rowPresenter.GetVisualChild<ContentPresenter>(columnIndex);

                TreeColumn treeColumn = column.GetValue(WPFMeta.TreeColumnProperty) as TreeColumn;

                //DataTemplate cellTemplate = new DataTemplate();
                //if (isEditing)
                //    cellTemplate.VisualTree = treeColumn.GenerateEditingFrameworkElementFactory();
                //else
                //    cellTemplate.VisualTree = treeColumn.GenerateFrameworkElementFactory();

                //cp.ContentTemplate = cellTemplate;
                cp.ContentTemplate = null;
                if (isEditing)
                    cp.Content = treeColumn.GenerateEditingFrameworkElement();
                else
                    cp.Content = treeColumn.GenerateFrameworkElement();

                columnIndex++;
            }
        }

    }
}
